#pragma once

#include <math/vector2.hpp>
#include <math/vector3.hpp>
#include <math/vector4.hpp>
#include <math/matrix2x2.hpp>
#include <math/matrix3x3.hpp>
#include <math/matrix4x4.hpp>
#include <math/quaternion.hpp>

#include <d3dx9math.h>




inline bool operator==(const D3DXVECTOR2& lhs, const math::vector2<float>& rhs)
{
	return math::number<float>(lhs.x) == math::number<float>(rhs.x) && math::number<float>(lhs.y) == math::number<float>(rhs.y);
}
///////////////////////////////////////////////////////////////////////////////////////////////////

inline bool operator==(const D3DXVECTOR3& lhs, const math::vector3<float>& rhs)
{
	return math::number<float>(lhs.x) == math::number<float>(rhs.x) && math::number<float>(lhs.y) == math::number<float>(rhs.y) && math::number<float>(lhs.z) == math::number<float>(rhs.z);
}
///////////////////////////////////////////////////////////////////////////////////////////////////

inline bool operator==(const D3DXVECTOR4& lhs, const math::vector4<float>& rhs)
{
	return math::number<float>(lhs.x) == math::number<float>(rhs.x) && math::number<float>(lhs.y) == math::number<float>(rhs.y) && math::number<float>(lhs.z) == math::number<float>(rhs.z) && math::number<float>(lhs.w) == math::number<float>(rhs.w);
}
///////////////////////////////////////////////////////////////////////////////////////////////////

inline bool operator==(const D3DXQUATERNION& lhs, const math::quaternion<float>& rhs)
{
	return math::number<float>(lhs.x) == math::number<float>(rhs.x) && math::number<float>(lhs.y) == math::number<float>(rhs.y) && math::number<float>(lhs.z) == math::number<float>(rhs.z) && math::number<float>(lhs.w) == math::number<float>(rhs.w);
}
///////////////////////////////////////////////////////////////////////////////////////////////////




bool operator==(const D3DMATRIX& lhs, const math::matrix4x4<float>& rhs)
{
	return math::number<float>(lhs._11) == math::number<float>(rhs._11) && math::number<float>(lhs._12) == math::number<float>(rhs._12) && math::number<float>(lhs._13) == math::number<float>(rhs._13) && math::number<float>(lhs._14) == math::number<float>(rhs._14) &&
		   math::number<float>(lhs._21) == math::number<float>(rhs._21) && math::number<float>(lhs._22) == math::number<float>(rhs._22) && math::number<float>(lhs._23) == math::number<float>(rhs._23) && math::number<float>(lhs._24) == math::number<float>(rhs._24) &&
		   math::number<float>(lhs._31) == math::number<float>(rhs._31) && math::number<float>(lhs._32) == math::number<float>(rhs._32) && math::number<float>(lhs._33) == math::number<float>(rhs._33) && math::number<float>(lhs._34) == math::number<float>(rhs._34) &&
		   math::number<float>(lhs._41) == math::number<float>(rhs._41) && math::number<float>(lhs._42) == math::number<float>(rhs._42) && math::number<float>(lhs._43) == math::number<float>(rhs._43) && math::number<float>(lhs._44) == math::number<float>(rhs._44);
}
///////////////////////////////////////////////////////////////////////////////////////////////////




/**
 * Write a 2-dimensional vector to an output stream.
 */
template <class Ch, class Tr>
std::basic_ostream<Ch, Tr>& operator<<(std::basic_ostream<Ch, Tr>& stream, const D3DXVECTOR2& v)
{
	stream << '(' << v.x << ',' << ' ' << v.y << ')';
	return stream;
}
///////////////////////////////////////////////////////////////////////////////////////////////

/**
 * Write a 3-dimensional vector to an output stream.
 */
template<class Ch, class Tr> inline
std::basic_ostream<Ch, Tr>& operator<<(std::basic_ostream<Ch, Tr>& stream, const D3DXVECTOR3& v)
{
	stream << '(' << v.x << ',' << ' ' << v.y << ',' << ' ' << v.z << ')';
	return stream;
}
///////////////////////////////////////////////////////////////////////////////////////////////

/**
 * Write a 4-dimensional vector to an output stream.
 */
template<class Ch, class Tr>
std::basic_ostream<Ch, Tr>& operator<<(std::basic_ostream<Ch, Tr>& stream, const D3DXVECTOR4& v)
{
	stream << '(' << v.x << ',' << ' ' << v.y << ',' << ' ' << v.z << ',' << ' ' << v.w << ')';
	return stream;
}
///////////////////////////////////////////////////////////////////////////////////////////////

/**
 * Write a quaternion vector to an output stream.
 */
template<class Ch, class Tr>
std::basic_ostream<Ch, Tr>& operator<<(std::basic_ostream<Ch, Tr>& stream, const D3DXQUATERNION& q)
{
	stream << '(' << q.w << ',' << ' ' << q.x << ',' << ' ' << q.y << ',' << ' ' << q.z << ')';
	return stream;
}
///////////////////////////////////////////////////////////////////////////////////////////////

/**
 * Write a 4x4-matrix to an output stream.
 */
template<class Ch, class Tr>
std::basic_ostream<Ch, Tr>& operator<<(std::basic_ostream<Ch, Tr>& stream, const D3DXMATRIX& m)
{
	stream << '(' << float4(m._11, m._12, m._13, m._14) << ',' << ' ' << float4(m._21, m._22, m._23, m._24) << ',' << ' ' << float4(m._31, m._32, m._33, m._34) << ','<< ' ' << float4(m._41, m._42, m._43, m._43) << ')';
	return stream;
}
///////////////////////////////////////////////////////////////////////////////////////////////
